package live.betterman.api.demo;

import cn.hutool.core.date.DateTime;
import lombok.Data;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

@Data
public class Cart {
    private Integer name;
    // 所有目标工位
    private LinkedList<Station> fullPath;
    // 所在产线
    private Line line;
    // 当前所在工位
    private Station currentStation;
    // 下一个目标工位
    private Station destStation;
    // 是否是产线上第一个
    private boolean isHeader;
    // 产线上所有的工位
    private List<Station> allStations;

    private Cart prev;
    private Cart next;

    public void move() throws InterruptedException {

        // head out
        if (fullPath.isEmpty()) {
            if(Objects.equals(line.getCarts().getFirst(), this)) {
                System.out.println(DateTime.now()+": cart" + name + " out");
                line.getCarts().poll();
                line.getCartsToMove().remove(this.name);

                if(!line.getCarts().isEmpty()) {
                    //
                    Cart headCart = line.getCarts().getFirst();
                    if (headCart != null) {
                        headCart.setHeader(true);
                        headCart.setPrev(null);
                        headCart.move();
                    }
                }
            }

            return;
        }

        if(line.getCartsToMove().contains(this.name)){
            System.out.println(DateTime.now()+": cart" + name + " moving, ignore");
            return;
        }
        Integer beforeDestStationCode = destStation == null ? null : destStation.getCode();
        Station station = fullPath.getFirst();// destination

        if (prev != null) {
            // 前车没在第一个目的工位 或 前车的目的工位在本车工位前面（挡住本车）
            if (prev.destStation == null || prev.destStation.getCode() < station.getCode()) {
                System.out.println(DateTime.now()+": cart" + name + " waiting");
                return;
            } else if (station.getCode() > prev.destStation.getCode() -1 && (prev.destStation.getCode() -1>=0)) {
                station = allStations.stream().filter(e->e.getCode() == prev.destStation.getCode() -1).findFirst().get();
                System.out.println(DateTime.now()+": case 1, cart" + name + " new station is "+ station.getCode());
            } else if(
                    prev.currentStation != null
                    && currentStation != null
                    && prev.currentStation.getCode() -1 > currentStation.getCode() //本车不是在前车的当前工位的前一个工位
                    && station.getCode() > prev.currentStation.getCode() -1 //本车目的工位在前车的当前工位的前一个工位之后
            ){
                station = allStations.stream().filter(e->e.getCode() == prev.destStation.getCode() -1).findFirst().get();
                System.out.println(DateTime.now()+": case 2, cart" + name + " new station is "+ station.getCode());
            }
        }
        destStation = station;

        // 前一个目的地与当前目的地相同，则不动； 可以考虑用状态值控制
        if (Objects.equals(station.getCode(), beforeDestStationCode)) {
            System.out.println(DateTime.now()+": ignore, cart" + name + " station is "+ station.getCode());
            return;
        }

        // async
        doMove(destStation);
    }

    private void doMove(Station finalStation){
        CompletableFuture.runAsync(() -> {
            // move to destStation
            try {
                line.getCartsToMove().add(this.getName());
                System.out.println(DateTime.now()+": cart " + name + " moving to " + finalStation.getCode());

                //TODO: just notify next
                if(next != null){
                    next.move();
                }

                int a = currentStation == null ? 0 : currentStation.getCode();
                int b = destStation == null ? 0 : destStation.getCode();
                if(b > 0) {
                    int count  = b - a;
                    if(count > 0) {
                        // 模拟移动
                        Thread.sleep(count * 1000L);
                    }
                }
                System.out.println(DateTime.now()+": cart " + name + " moved to " + finalStation.getCode());

                // 移动完成
                this.currentStation = finalStation;
                if (Objects.equals(finalStation.getCode(), fullPath.getFirst().getCode())) {
                    fullPath.poll();
                }

                line.getCartsToMove().remove(this.name);

                if(prev == null || prev.destStation.getCode() -1 > currentStation.getCode()) {
                    //移动到下一工位
                    move();
                }

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }catch (Exception e){
                e.printStackTrace();
            }finally {

            }

        });
    }


}
